$.mcCube.listing = $.class.create({
    /* listing */ construct : function(name, config){
        this.name    = name;
        this.config  = config;
        this.theme   = $.mcCube.theme.instance(config.theme);
        this.nodes   = {};
        this.columns = {};
        this.items   = [];
        this.menu    = this.child('menu');
        if(config.actions){
            this.actions = this.child('actions', [config.actions]);
        }
    },

    /**  */
    reset : function(type){
        this.nodes   = {};
        this.columns = {};
        this.items   = [];
        return this;
    },

    /**  */
    getColumns : function(type){
        if(!type){
            return this.columns;
        }

        var cols = [];
        for(var column in this.columns){
            if(this.columns[column][type]){
                cols.push(this.columns[column]);
            }
        }
        return cols;
    },

    /**  */
    setColumns : function(columns){
        for(var column in columns){
            this.setColumn(column, columns[column]);
        }
        return this;
    },

    /**  */
    setColumn : function(name, config){
        this.columns[name] = this.child('column', [name, config]);
        return this;
    },

    /**  */
    setItems : function(items, config){
        for(var item in items){
            this.setItem(item, items[item], config);
        }
        return this;
    },

    /**  */
    setItem : function(index, values, config){
        this.items.push(this.child('row', [index, values, config]));
        return this;
    },

    /**  */
    render : function(selector, parent){
        if(!selector)
            selector = '#'+ this.name;

        this.node = $(selector, parent)
            .append(this.renderMenu())
            .append(this.renderList())
        ;
    },

    /**  */
    renderMenu : function(){
        this.nodes.menu = $('<div></div>')
            .attr('class', this.config.cssClass +'-menu')
            .append(this.menu.render());

        return this.nodes.menu;
    },

    /**  */
    renderListHead : function(){
        var thead = $('<thead><tr><td></td></tr></thead>');
        for(var column in this.columns){
            $('tr', thead).append(this.columns[column].render());
        }
        return thead;
    },

    /**  */
    renderList : function(){
        if(!this.items.length){
            return;
        }

        var tbody = $('<tbody></tbody>');
        for(var item in this.items){
            tbody.append(this.items[item].render());
        }

        return this.nodes.list = $('<table></table>')
            .attr('class', this.config.cssClass)
            .append(this.renderListHead())
            .append(tbody)
        ;
    }
}).child('actions', ['actions'], {
    /* listing.actions */ construct : function(config){
        this.config = config;

        var columns = [];
        if(columns = this.parent.getColumns('filter')){
            if(!this.config.filter){
                this.config.filter = {};
            }
            this.config.filter.columns = columns;
        }
    },

    /**  */
    getList : function(){
        return this.config;
    }
}).child('menu', {
    /* listing.menu */ construct : function(config){
        this.node   = null;
        this.config = config;
    },

    /**  */
    renderItem : function(action, config){
        var $this = this;
        var li    = $('<li></li>');
        li.append(this.parent.theme.icon(action)
            .click({'action': action}, function(event){
                $this.parent.actions.fire(event.data.action);
            })
        );

        if(config.label){
            li.append(config.label);
        }

        return li;
    },

    /**  */
    render : function(){
        this.node = $('<ul></ul>');

        var start   = true;
        var actions = this.parent.actions.getList();
        for(var action in actions){
            if(!start){
                $('<span> | </span>').appendTo(this.node);
            }
            this.node.append(this.renderItem(action, actions[action]));
            start = false;
        }

        return this.node;
    }
}).child('column', {
   /* listing.column */ construct : function(name, config){
        this.name   = name;
        this.config = config;
    },

    /**  */
    getRealField : function(){
        return this.config.linkedBy ? this.config.linkedBy : this.name;
    },

    /**  */
    getType : function(){
        return this.config.type;
    },

    /**  */
    render : function(){
        var $this = this;
        var th = $('<th></th>');
        th.html(this.config.label);
        return th;
    }
}).child('row', {
    /* listing.row */ construct : function(index, values, config){
        this.name    = name;
        this.values  = values;
        this.config  = config;
        this.columns = {};
        this.actions = this.child('actions', [config.actions]);

        for(var column in this.parent.columns){
            this.columns[column] = this.child('column', [this.parent.columns[column]]);
        }
    },

    /**  */
    getValues : function(withAllRowValues){
        var values = {};
        if(withAllRowValues){
            values = this.values;
        }

        for(var column in this.columns)
            values[this.columns[column].referer.getRealField()] = this.columns[column].getIValue();

        return values;
    },

    /**  */
    render : function(){
        this.node = $('<tr></tr>');
        this.node.append(this.actions.render());
        for(var column in this.columns){
             this.node.append(this.columns[column].render());
        }
        return this.node;
    }
});

$.mcCube.listing.child('row').child('actions', ['actions'], {
    /* listing.row.actions */ construct : function(config){
        this.node       = null;
        this.config     = config;
        this.components = null;
        this.oldAtion   = '';
    },

    view : function(config){
        this.runComponent('view', config);
    },

    edit : function(config){
        this.runComponent('edit', config);
    },

    delete : function(config){
       this.runComponent('delete', config);
    },

    editDyn : function(){
        if(this.config.edit.target){
            $.mcCube.tools.ajax.post(
                  this.config.edit.target.format(this.parent.values)
                , function(datas){

                }
                , {'dynamic' : true, 'edit': this.parent.getValues()}
            );
        }
    },

    resetSelectedRow : function(){
        if(this.root.selectedRow
            && this.root.selectedRow.actions.components
        ){
            this.root.selectedRow.actions.components.close();
            this.root.selectedRow.actions.oldAtion = '';
            this.root.selectedRow = null;
        }
    },

    runComponent : function(action, config, datas){
        if(this.components){
            this.components = this.components.close();
            if(this.oldAtion == action){
                this.oldAtion = '';
                this.root.selectedRow = null;
                return;
            }
        }

        this.resetSelectedRow();

        var $this = this;
        switch(config.mode){
            case 'link' :
                location.href = config.target.format($this.parent.values);
            break;
            case 'confirm' :
            case 'popin'   :
                this.components = $.mcCube.popin.singleton({
                    'close' : function(){
                        $this.components = null;
                        $this.root.selectedRow.actions.components = null;
                    }
                });
            break;
            case 'slider'  :
                this.components = this.parent.child(config.mode);
            break;
        }

        if(this.components && config.target){
            this.components.load(
                config.target.format($this.parent.values)
            );
        }

        this.oldAtion = action;
        this.root.selectedRow = this.parent;
    },

    /**  */
    render : function(){
        this.node  = $('<td></td>').attr('class', 'listing-item-actions');

        var $this = this;
        for(var action in this.config){
            this.node.append(this.root.theme.icon(action, this.config[action])
                .click({'action': action}, function(event){
                    $this.fire(event.data.action);
                })
            );
        }
        return this.node.css('width', $.size(this.config) * 15);
    }
}).child('slider', {
    /* listing.slider */ construct : function(){
        this.node = null;
    },

    close : function(){
        this.node.remove();
        this.parent.node.removeClass('rowItemSelected');
        return null;
    },

    open : function(datas){
        this.create();

        this.parent.node.after(
            this.node
        ).addClass('rowItemSelected');
        this.node.toggle('highlight');
        return this;
    },

    load : function(url, noAutoOpen){
        var $this = this;
        $.mcCube.tools.ajax.post(url, function(datas){
            $this.create().open().html(datas);
        });
        return this;
    },

    html : function(html){
        $('.itemViewDetails', this.node).html(html);
        return this;
    },

    /**  */
    create : function(datas){
        if(!this.node){
            this.node  = $('<tr class="rowItemDetails" style="display:none;">'
                +'<td colspan="'+ $('td', this.parent.node).length +'">'
                    +'<div class="itemViewDetails"></div>'
                +'</td>'
            +'</tr>');
        }
        return this;
    }
});

$.mcCube.listing.child('row').child('column', {
    /* listing.row.column */ construct : function(referer){
        this.nodes   = {};
        this.referer = referer;
        this.hValue  = this.parent.values[this.referer.name];
        this.iValue  = this.getIValue();
    },

    /**  */
    getIValue : function(){
        if(this.iValue){
            return this.iValue;
        }
        else{
            if(this.referer.config.linkedBy){
                return this.parent.values[this.referer.config.linkedBy];
            }
            return this.parent.values[this.referer.name];
        }
    },

    /**  */
    getField : function(){
        var field  = null;
        var config = this.referer.config.dynEdit;
        switch(config.type){
            case 'select' :
                field = $.form.select(config.options, this.iValue, config);
            break;
            default       :
                field = $.form[config.type](this.iValue);
            break;
        }

        var $this = this;
        switch(config.type){
            case 'date' :
                field.datepicker({
                    onClose : function(value, inst){
                        if(value != $this.value){
                            $this.iValue = $this.hValue = value;
                        }
                        $this.onFocusOut();
                    }
                });
            break;
            default     :
                field.focusout(function(){
                    $this.iValue = $(this).val();
                    switch(config.type){
                        case 'select' :
                            $this.hValue = $(':selected', this).html();
                        break;
                        case 'textarea' :
                            $this.hValue = $.nlToBr($this.iValue);
                        break;
                        default       :
                            $this.hValue = $this.iValue;
                        break;
                    }
                    $this.onFocusOut();
                });
            break;
        }
        return field;
    },

    /**  */
    onFocusOut : function(){
        this.parent.actions.editDyn();


        if(!this.nodes.field)
            return;

        this.nodes.td.empty();
        this.nodes.field = null;
        this.nodes.td.html(this.hValue);
    },

    /**  */
    onClick : function(){
        if(this.nodes.field){
            return;
        }

        this.nodes.field = this.getField();
        this.nodes.field.appendTo(this.nodes.td.empty()).focus();
        this.nodes.field.focus();
    },

    /**  */
    render : function(){
        this.nodes.td = $('<td></td>');
        this.nodes.td.html(this.hValue);

        var $this = this;
        if(this.referer.config.dynEdit){
            this.nodes.td.click(function(){
                $this.onClick();
            });
        }
        return this.nodes.td;
    }
});